#include "JobsQueue.cuh"



JobsQueue::JobsQueue(int capacity) : jobs(capacity)
{
	unsigned int init_val = 0;
	check(cudaMalloc(&(this->next_job_index), sizeof(unsigned int)), "Allocating jobs queue");
	check(cudaMemcpy(this->next_job_index, &init_val, sizeof(unsigned int), cudaMemcpyHostToDevice), "Copying first job index on jobs queue");
	this->closed = false;
}

__device__ Job JobsQueue::next_job()
{
	if(!closed)
	{
		printf("(UNSAFE) Should not get objects before closing!\n");
	}

	int index = atomicInc(next_job_index, LARGE_NUMBER);//jobs.size_of());

#ifdef DEBUG
	if(DEBUG_SHOULD_PRINT(threadIdx.x, blockIdx.x))
	{
		printf("Chose job of index %d of %d jobs\n", index, jobs.size_of());
	}
#endif

	if(index >= this->jobs.size_of())
	{
		Job j;
		j.number_of_literals = 0;
		return j;
	}
	else
	{
		return jobs.get(index);
	}

}

__host__ __device__ void JobsQueue::close()
{
	closed = true;
}

__host__ void JobsQueue::add(Job & job)
{

	if(closed)
	{
		printf("Cannot add after closed.\n");
		return;
	}

	jobs.add(job);


	if(job.number_of_literals > size_of_largest_job)
		size_of_largest_job = job.number_of_literals;

}

/**
 * Returns the number of literals of the job with the most literals.
 *
 */
__host__ __device__ int JobsQueue::largest_job_size()
{
	return size_of_largest_job;

}

__host__ __device__ int JobsQueue::number_of_jobs()
{
	return jobs.size_of();
}

__host__ __device__ void JobsQueue::print_jobs()
{

	printf("There are %d jobs\n", number_of_jobs());
	for(int i = 0; i < number_of_jobs(); i++)
	{
		Job j = jobs.get(i);
		print_job(j);
	}
}

__host__ Job mkJob_dev(Lit* literals, int number_of_literals)
{
	Lit* dev_lits;

	check(cudaMalloc(&dev_lits, number_of_literals*sizeof(Lit)), "Allocating job on dev");

	check(cudaMemcpy(dev_lits, literals, number_of_literals*sizeof(Lit),
			cudaMemcpyHostToDevice), "Copying job to dev");

	Job job;
	job.literals = dev_lits;
	job.number_of_literals = number_of_literals;

	return job;

}

__host__ __device__ void print_job(Job & job)
{
#ifdef __CUDA_ARCH__
	printf("Job: ");
	for(int i = 0; i < job.number_of_literals; i++)
	{
		print_lit(job.literals[i]);
		printf(" ");
	}

	printf("\n");
#else
	Lit* literals_host = (Lit*) malloc(sizeof(Lit)*job.number_of_literals);
	cudaMemcpy(literals_host, job.literals,
			sizeof(Lit)*job.number_of_literals, cudaMemcpyDeviceToHost);
	printf("Job: ");
	for(int i = 0; i < job.number_of_literals; i++)
	{
		print_lit(literals_host[i]);
		printf(" ");
	}
	printf("\n");
#endif
}
